#!/usr/bin/env python3
"""Simple macro processor"""

#
# Copyright 2024  Odin Kroeger
#
# This file is part of SieveManager.
#
# SieveManager is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# SieveManager is distributed in the hope that it will be useful,
# but WITHOUT ALL WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with SieveManager. If not, see
# <https://www.gnu.org/licenses/>.
#

#
# Modules
#

from contextlib import suppress
from getopt import getopt, GetoptError
from os import remove, rename, strerror
from os.path import dirname, basename, exists, join
from shutil import copy
from signal import SIGHUP, SIGINT, SIGTERM
from string import Template
# pylint: disable=redefined-builtin
from sys import argv, exit, stderr
from typing import NoReturn

import logging
import sievemgr


#
# Metadata
#

__author__ = 'Odin Kroeger'
__copyright__ = '2024 Odin Kroeger'
__version__ = '0.1'


#
# Functions
#

def showversion() -> NoReturn:
    """Print version to standard output and exit."""
    print(f"macrop (SieveManager) {__version__}\nCopyright {__copyright__}")
    exit(0)


#
# Main
#

@sievemgr.SignalCaught.catch(SIGHUP, SIGINT, SIGTERM)
def main() -> NoReturn:
    """macrop - replace variables with SieveManager globals

    Usage: macrop template output

    Options:
        -V   Show version information.
        -h   Show this help screen.

    Report bugs to: <https://github.com/odkr/sievemgr/issues>
    Home page: <https://odkr.codeberg.page/sievemgr>
    """
    progname = basename(argv[0])
    logging.basicConfig(format=f'{progname}: %(message)s')

    try:
        opts, args = getopt(argv[1:], 'hV', ['help', 'version'])
    except GetoptError as err:
        sievemgr.error(err, status=2)

    for opt, _ in opts:
        if opt in ('-h', '--help'):
            sievemgr.showhelp(main)
        if opt in ('-V', '--version'):
            showversion()

    try:
        source, target = args
    except ValueError:
        print(f'usage: {progname} [-h] source target', file=stderr)
        exit(2)

    swap = join(dirname(source), '.' + basename(source) + '.swp')
    macros = {k: v for k, v in sievemgr.__dict__.items()
              if isinstance(v, (int, str))}
    try:
        with open(swap, 'w') as swapfile:
            with open(source) as sourcefile:
                for line in sourcefile:
                    sub = Template(line).safe_substitute(macros)
                    print(sub, file=swapfile, end='')
        if exists(target):
            copy(target, target + '.bak')
        rename(swap, target)
    except FileNotFoundError as err:
        sievemgr.error(f'{err.filename}: {strerror(err.errno)}')
    except OSError as err:
        sievemgr.error(strerror(err.errno))
    finally:
        with suppress(FileNotFoundError):
            remove(swap)
    exit(0)


if __name__ == '__main__':
    main()
